import json
import uuid
import socket

import qrcode
from django import http
from django.shortcuts import render
# Create your views here.
from django.views import View
from paho import mqtt

from apps.medicine.models import Medicals, Medical_loads, User_medicine
from apps.user.models import User
from send_medicine.settings import BASE_DIR
from utils.medicine_request_utils import MyThread, search2, SearchMedicine3
from utils.mqtt import MqttClient
from utils.response_code import RETCODE
from utils.sun_jwt import JWT_Handler


class Search_Medicines(View):
    """查询药品"""

    def get(self, request):
        name = request.GET.get('name')
        try:
            # 随便查一条数据，如果不报错，则说明里面有数据
            a = Medicals.objects.get(name=name)
            Medical_loads.objects.get(medical=a, num=18)
            m = 1
        except:
            # 如果报错了，则说明数据库中没有这个药品，需要爬取到数据库中
            m = 0

        if m == 0:
            # 爬取数据到数据库中
            t = MyThread(search2, args=(name,))
            t.start()  ##启动线程
            # 判断是否有这个药品
            try:
                # 有这个药品，则保存20条数据到数据库
                a = Medicals.objects.get(name=name)
            except:
                # 没有这个药品则创建药品
                Medicals.objects.create(
                    name=name
                )
                a = Medicals.objects.get(name=name)

            # 判断是否已经存储过数据了
            try:
                # 随便查一条数据，如果不报错，则说明里面有数据
                Medical_loads.objects.get(medical=a, id=18)
                b = 1
            except:
                # 如果报错了，则说明里面没有数据
                b = 0
            if b == 1:
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '请勿重复存储'})
            else:
                try:
                    for num in range(20):
                        num += 1
                        search = SearchMedicine3(name, num)
                        data = search.data()
                        num = int(num)
                        name_in = data[num]['name']
                        img = data[num]['img_url']
                        suit = data[num]['suit']
                        usemethod = data[num]['usemethod']
                        lelment = data[num]['lelment']
                        bad = data[num]['bad']
                        err = data[num]['err']
                        heed = data[num]['heed']
                        savemethod = data[num]['savemethod']
                        a = Medicals.objects.get(name=name)
                        Medical_loads.objects.create(
                            img_url=img,
                            suit=suit,
                            usemethod=usemethod,
                            lelment=lelment,
                            bad=bad,
                            err=err,
                            heed=heed,
                            savemethod=savemethod,
                            num=num,
                            name=name_in,
                            medical=a
                        )
                except Exception as e:
                    return http.JsonResponse({'code': 'err'})
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '已存储到数据库', 'data': t.get_result()})
        elif m == 1:
            # 从数据库中查询出药品信息
            try:
                n = Medicals.objects.get(name=name)
                medicals = n.medical.all()
                data = json.loads(json.dumps(list(medicals.values())))
            except Exception as e:
                return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '药品不在数据库中'})
            return http.JsonResponse({'data': data})
        else:
            pass


class Medicines_state(View):
    """药品状态"""

    def get(self, request):
        """查询药品状态
        > 0为已经取药
        > 1为还未取药
        """
        token = request.GET.get('token')
        try:
            user = User.objects.get(token=token)
            medicines = User_medicine.objects.filter(user=user)
            if len(medicines) == 0:
                return http.JsonResponse({'code': RETCODE.OK, 'current': 1})
            else:
                data_dict = {}
                for n in range(len(medicines)):
                    dict_in = {}
                    dict_in['name'] = medicines[n].name
                    dict_in['number'] = medicines[n].number
                    dict_in['message'] = medicines[n].message
                    dict_in['state'] = medicines[n].status
                    dict_in['send_data'] = medicines[n].send_data
                    data_dict[n] = dict_in
                return http.JsonResponse({'code': RETCODE.OK, 'data': data_dict, 'current': 2})
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '没有该用户', 'current': 0})

    def put(self, request):
        """修改状态为已经领取，只允许一个一个药品修改"""
        token = json.loads(request.body.decode()).get('token')
        name = request.GET.get('name')
        state = request.GET.get('state')
        user = User.objects.get(token=token)
        try:
            medicines = User_medicine.objects.filter(user=user, name=name)
            if len(medicines) == 0:
                return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '没有该药品，请查看该用户的药品是否正确'})
            else:
                medicines.update(status=state)
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '状态修改成功'})
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.NODATAERR, 'errmsg': '没有该药品，请查看该用户的药品是否正确'})


class Send_medicines(View):
    """医院发药接口"""

    def post(self, request):
        data = json.loads(request.body.decode())
        token = data.get('token')
        name = request.GET.get('name')
        number = request.GET.get('number')
        message = request.GET.get('message')
        try:
            user = User.objects.get(token=token)
            User_medicine.objects.create(user=user, name=name, number=number, message=message, status=1)
            return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发药成功'})
        except Exception as e:
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '发药失败'})


class QRCode(View):
    """取药二维码
    CheckJwt类视图是用来加密解密的
    二维码取药逻辑：
        小程序：通过QRCode接口生成二维码（二维码的message为通过JWT加密的用户的token的小写（因为二维码硬件模块没法识别大写字母））格式为：openid&encodingdata
        树莓派：扫描二维码，扫描出来的数据在这里留着
              查询这个用户的token，并进行加密。将加密后的数据全部变为小写
              将扫描出来的数据，和刚刚加密后小写的数据对比，如果相同就验证通过
        小程序负责生成带有openid和加密openid的二维码
        树莓派负责将数据通过接口验证
    """

    def get(self, request):
        message = request.GET.get('message')
        # jwt = JWT_Handler()
        # data = str(jwt.sun_encode(message))
        # message = message + ',' + data
        img = qrcode.make(message)
        uuid_name = str(uuid.uuid4())
        img.save('collected_static/' + uuid_name + '.jpg')
        # res = '127.0.0.1:8000/static/' + uuid_name + '.jpg'
        # res = '120.78.168.67:9876/static/' + uuid_name + '.jpg'
        # 通过获取hostname来判断是否为服务器还是本机
        hostname = socket.gethostname()  # DESKTOP-8F829M6本机
        if hostname == 'DESKTOP-8F829M6':
            res = '127.0.0.1:8000/static/' + uuid_name + '.jpg'
        else:
            res = '120.78.168.67:9876/static/' + uuid_name + '.jpg'
        return http.JsonResponse({'code': RETCODE.OK, 'image': res})


class JwtView(View):
    """jwt加密解密"""
    def get(self, request):
        # status为encode就是加密，decode就是解密
        status = request.GET.get('status')
        message = request.GET.get('message')
        if status == '' or message == '':
            return http.JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': 'status为空或message为空'})
        jwt = JWT_Handler()
        if status == 'encode':
            # 加密
            data = jwt.sun_encode(message)
        elif status == 'decode':
            # 解密
            data = jwt.sun_decode(message)
        else:
            pass
        return http.JsonResponse({'code': RETCODE.OK, 'data': data})


class CheckJwt(View):
    """验证扫描的二维码是否可以取药
    传进来的是加密后的数据（openid&decodings)
    验证数据匹不匹配，如果匹配就发药
                  如果不匹配就不发药


    取药流程：
            小程序：0、小程序的created生命周期中生成二维码
                  1、通过vuex获取到openid
                  2、通过JWT接口对openid进行加密，并拼接成（openid&JWT)形式
                  3、使用二维码接口将拼接后的字段生成为二维码
            树莓派：1、请求CheckJwt接口，也就是本接口对数据进行校验

    """
    def get(self, request):
        # 这个message中存的是openid好加密后的信息（小写的）（openid就是token）
        message = request.GET.get('message')
        # 传进来的message前面是openid，后面是加密的信息（小写的），通过&连接。转为数组
        message_list = message.split(',')
        openid = message_list[0]  # openid（就是token登录凭证）
        encodings = message_list[1]  # 加密后的openid
        jwt = JWT_Handler()
        # 对openid加密并将转为小写，进行对比，如果相同则匹配成功，反之不成功
        data = jwt.sun_encode(openid)
        if data.lower() == encodings:
            try:
                user = User.objects.get(token=openid)
                medicines = User_medicine.objects.filter(user=user)
                # 修改用户药品状态
                # > 0为已经取药
                # > 1为还未取药
                medicines.update(status=0)
                # 转动药品舵机，将药品打下.
                mqtt = MqttClient()
                mqtt.publish('dj', 'djon')
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发药成功'})
                # for n in range(len(medicines)):
                #     # 修改用户药品状态
                #     # > 0为已经取药
                #     #> 1为还未取药
                #     medicines[n].status = 0
                #     medicines[n].save()
                #     # 转动药品舵机，将药品打下
                #     # mqtt = MqttClient()
                #     # mqtt.publish('dj', 'djon')
                #     pass
            except Exception as e:
                return http.JsonResponse({'code': RETCODE.USERERR, 'errmsg': '没有此用户'})
            # return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '匹配成功'})
